/*
 * Unidata Platform Community Edition
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 * This file is part of the Unidata Platform Community Edition software.
 *
 * Unidata Platform Community Edition is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Unidata Platform Community Edition is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

package org.unidata.mdm.data.service.segments.relations.restore;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import org.springframework.stereotype.Component;
import org.unidata.mdm.core.type.timeline.TimeInterval;
import org.unidata.mdm.core.type.timeline.Timeline;
import org.unidata.mdm.data.context.RelationRestoreContext;
import org.unidata.mdm.data.dto.RestoreRelationDTO;
import org.unidata.mdm.data.module.DataModule;
import org.unidata.mdm.data.type.data.EtalonRelation;
import org.unidata.mdm.data.type.data.OriginRelation;
import org.unidata.mdm.system.type.pipeline.Finish;
import org.unidata.mdm.system.type.pipeline.Start;

/**
 * @author Mikhail Mikhailov on Nov 24, 2019
 */
@Component(RelationRestoreFinishExecutor.SEGMENT_ID)
public class RelationRestoreFinishExecutor extends Finish<RelationRestoreContext, RestoreRelationDTO> {
    /**
     * This segment ID.
     */
    public static final String SEGMENT_ID = DataModule.MODULE_ID + "[RELATION_RESTORE_FINISH]";
    /**
     * Localized message code.
     */
    public static final String SEGMENT_DESCRIPTION = DataModule.MODULE_ID + ".relation.restore.finish.description";
    /**
     * Constructor.
     */
    public RelationRestoreFinishExecutor() {
        super(SEGMENT_ID, SEGMENT_DESCRIPTION, RestoreRelationDTO.class);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public RestoreRelationDTO finish(RelationRestoreContext iCtx) {

        RestoreRelationDTO result = new RestoreRelationDTO();
        Timeline<OriginRelation> next = iCtx.nextTimeline();

        if (Objects.nonNull(next) && next.isNotEmpty()) {

            EtalonRelation etalon = null;
            List<EtalonRelation> periods = new ArrayList<>(next.size());

            // Select point for traditional single "etalon" return value
            // null (now) or forDate will be taken for the whole record
            Date point = null;
            if (iCtx.isPeriodRestore()) {
                point = iCtx.getValidFrom() == null ? iCtx.getValidTo() : iCtx.getValidFrom();
            } else {
                point = iCtx.getForDate() == null ? new Date() : iCtx.getForDate();
            }

            for (TimeInterval<OriginRelation> interval : next) {

                if (Objects.isNull(etalon) && interval.isInRange(point)) {
                    etalon = interval.getCalculationResult();
                }

                periods.add(interval.getCalculationResult());
            }

            result.setEtalon(etalon);
            result.setPeriods(periods);
        }

        result.setRelationKeys(iCtx.relationKeys());
        result.setRights(iCtx.accessRight());
        result.setValidFrom(iCtx.getValidFrom());
        result.setValidTo(iCtx.getValidTo());

        return result;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean supports(Start<?, ?> start) {
        return RelationRestoreContext.class.isAssignableFrom(start.getInputTypeClass());
    }
}
